package com.third.customer.site.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.third.customer.model.data.JsonResult;
import com.third.customer.model.data.UserType;
import com.third.customer.model.tables.Area;
import com.third.customer.model.tables.Customer;
import com.third.customer.model.tables.CustomerGroup;
import com.third.customer.service.AreaService;
import com.third.customer.service.CustomerGroupService;
import com.third.customer.service.CustomerService;
import com.third.customer.service.data.CustomerReport;
import com.third.customer.service.data.CustomerReq;
import com.third.customer.service.data.CustomerSwitchReq;
import com.third.customer.service.exception.ThirdBadRequestException;
import com.third.customer.service.utils.ExcelUtils;
import com.third.customer.service.utils.PageResult;
import com.third.customer.site.UserInfo;
import com.third.customer.site.controller.req.CustomerDownloadReq;
import com.third.customer.site.controller.req.CustomerHistoryReq;
import com.third.customer.site.controller.req.CustomerQueryReq;
import com.third.customer.site.controller.resp.CustomerResp;
import com.third.customer.site.support.ThirdAuth;
import com.third.customer.site.support.ThirdUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Created by hehuaichun on 2020/5/22.
 */
@RestController
@RequestMapping("/customers")
@Slf4j
public class CustomerCtrl {

    @Autowired
    private CustomerService customerService;

    @Autowired
    private AreaService areaService;

    @Autowired
    private CustomerGroupService groupService;

    @GetMapping
    @ThirdAuth(UserType.ORDINARY)
    public JsonResult list(@ThirdUser UserInfo userInfo, CustomerQueryReq req) {
        Page<Customer> page = customerService.list(req.toParam(userInfo.getCompanyId()));
        List<Long> areaIds = page.getRecords().stream().map(Customer::getAreaId).distinct().collect(Collectors.toList());
        List<Long> groupIds = page.getRecords().stream().map(Customer::getGroupId).distinct().collect(Collectors.toList());
        Map<Long, Area> areaMap = areaService.getByIds(userInfo.getCompanyId(), areaIds)
                .stream().collect(Collectors.toMap(Area::getId, Function.identity()));
        Map<Long, CustomerGroup> groupMap = groupService.getByIds(userInfo.getCompanyId(), groupIds)
                .stream().collect(Collectors.toMap(CustomerGroup::getId, Function.identity()));
        List<CustomerResp> resps = page.getRecords().stream().map(c ->
                CustomerResp.convert(c, areaMap.getOrDefault(c.getAreaId(), new Area()),
                        groupMap.getOrDefault(c.getGroupId(), new CustomerGroup()))).collect(Collectors.toList());
        return JsonResult.ok(PageResult.build(page, resps));
    }

    @GetMapping("/{id}")
    @ThirdAuth(UserType.ORDINARY)
    public JsonResult getById(@ThirdUser UserInfo userInfo,
                              @PathVariable Long id) {
        Customer customer = customerService.getById(userInfo.getCompanyId(), id);
        CustomerGroup group = groupService.getById(customer.getCompanyId(), customer.getGroupId());
        Area area = areaService.getById(customer.getCompanyId(), customer.getAreaId());
        return JsonResult.ok(CustomerResp.convert(customer, area, group));
    }

    @PostMapping
    @ThirdAuth(UserType.ORDINARY)
    public JsonResult create(@ThirdUser UserInfo userInfo,
                             @Valid CustomerReq req) {
        req.validateForCreate();
        return JsonResult.ok(customerService.create(userInfo.getCompanyId(), req));
    }

    @PostMapping("/{id}/modify")
    @ThirdAuth(UserType.ORDINARY)
    public JsonResult modify(@ThirdUser UserInfo userInfo,
                             @PathVariable Long id,
                             @Valid CustomerReq req) {
        req.validateForModify();
        return JsonResult.ok(customerService.modify(userInfo.getCompanyId(), id, req));
    }

    @PostMapping("/{id}/delete")
    @ThirdAuth(UserType.ORDINARY)
    public JsonResult delete(@ThirdUser UserInfo userInfo,
                             @PathVariable Long id) {
        return JsonResult.ok(customerService.delete(userInfo.getCompanyId(), id));
    }

    @PostMapping("/{id}/switch")
    @ThirdAuth(UserType.ORDINARY)
    public JsonResult switchGroup(@ThirdUser UserInfo userInfo,
                                  @PathVariable Long id,
                                  @Valid CustomerSwitchReq req) {
        return JsonResult.ok(customerService.switchGroup(userInfo.getCompanyId(), id, req));
    }

    @PostMapping("/upload")
    @ThirdAuth(UserType.ORDINARY)
    public JsonResult upload(@ThirdUser UserInfo userInfo,
                             @RequestParam(name = "file") MultipartFile file,
                             @RequestParam(defaultValue = "false") Boolean forceUpdate) {
        if (file == null) {
            throw new ThirdBadRequestException("请添加上传文件!");
        }
        try {
            customerService.analysis(userInfo.getCompanyId(), file, forceUpdate);
        } catch (Exception e) {
            log.error("failed to analysis file", e);
            return JsonResult.internalError("analysis_fail");
        }
        return JsonResult.ok();
    }

    @PostMapping("/download")
    @ThirdAuth(UserType.ORDINARY)
    public JsonResult download(@ThirdUser UserInfo userInfo,
                               @Valid CustomerDownloadReq req,
                               HttpServletResponse response) {
        List<CustomerReport> reports = customerService.getReports(req.toParam(userInfo.getCompanyId()));
        ExcelUtils.write(response, reports, "customer");
        return JsonResult.ok();
    }

    @PostMapping("/histories")
    @ThirdAuth(UserType.ORDINARY)
    public JsonResult histories(@Valid CustomerHistoryReq req) {
        return JsonResult.ok(PageResult.build(customerService.histories(req.toParam())));
    }

}
